package app.widget;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import app.utils.CommonUtils;
import app.utils.Tools;

import com.longevityassistant.activity.R;

public class CalendarView extends LinearLayout implements OnClickListener{
    
    public static final String TAG = CalendarView.class.getSimpleName();
    
    /**
     * 星期的第一天: 星期一或星期日
     */
    private static final int FISRT_DAY_OF_WEEK = Calendar.SUNDAY;
    
    /**
     * 日期标头星期的高度
     */
    private static final int DAY_HEADER_HEIGHT = 24;
	
    /**
     * 日历中所有的单元格列表
     */
	private ArrayList<DateCell> mDayCells = new ArrayList<DateCell>();
	
	/**
	 * 布局实例化器
	 */
	private LayoutInflater mInflater;
	
	private Calendar calStartDate =  CommonUtils.getCurrentTimeByCalendar();
	
	private Calendar calToday =  CommonUtils.getCurrentTimeByCalendar(); 
	
	/**
	 * 当用户点击日历的时候点击的日期
	 */
	private Calendar mSelectedDate =  Calendar.getInstance();
	
	/**
     * 当前显示的月份
     */
    private Calendar mCurrentMonth =  CommonUtils.getCurrentTimeByCalendar();
	
	/**
	 * 日历中显示日期的容器
	 */
	private LinearLayout llCalendarDaysContainer;
	
	// 当前月
	private TextView btnToday = null;
	
	/**
	 * 当前的月份
	 */
	private int mMonthViewCurrentMonth = 0;
	
	/**
	 * 当前的年份
	 */
	private int mMonthViewCurrentYear = 0;
	
	/**
	 * 日历中日期单元格的高宽
	 */
	private int cellWidth;
	private int cellHeight;
	
	/**
	 * 当前月份下的事件列表
	 */
    private List<EventState> mIncomeAndExpensesStates;
    
    /**
     * 日期点击事件监听器
     */
    private OnDateClickListener onDateClickListener;

    /**
     * 月份切换监听器
     */
    private OnMonthChangeListener onMonthChangeListener;
  
    
	public CalendarView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public CalendarView(Context context) {
		super(context);
		init();
	}
	
	private void init() {
	    mInflater = LayoutInflater.from(getContext());
	    
        cellWidth = getResources().getDimensionPixelSize(R.dimen.calendar_cell_width); 
        cellHeight = getResources().getDimensionPixelSize(R.dimen.calendar_cell_height);
	   
        mSelectedDate.clear();
	    
        addView(mInflater.inflate(R.layout.app_widget_calander, null), new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        
        btnToday = (TextView) findViewById(R.id.tv_current_month);
        llCalendarDaysContainer = (LinearLayout) findViewById(R.id.ll_content);
        
        ImageButton btnPrev = (ImageButton) findViewById(R.id.ibtn_pre_month);
        ImageButton btnNext = (ImageButton) findViewById(R.id.ibtn_next_month);
        LinearLayout llHeader = (LinearLayout) findViewById(R.id.ll_header);
        
        btnToday.setOnClickListener(this);
        btnPrev.setOnClickListener(this);
        btnNext.setOnClickListener(this);
        
        generateHead(llHeader);
        
        for (int i = 0; i < 6; i++) {
            llCalendarDaysContainer.addView(generateCalendarRow());
        }
		
        setTodayViewItem();
	}
	
	/**
	 * 产生日历的头部星期显示的View
	 * @param llHeaderContainer
	 */
	private void generateHead(LinearLayout llHeaderContainer) {
        String[] headers = getResources().getStringArray(R.array.calendar_header_weekds);
        for (int i = 0; i < 7; i++) {
            TextView tvDay = new TextView(getContext());
            tvDay.setTextSize(14f);
            tvDay.setTextColor(getResources().getColor(R.color.col_pa03));
            tvDay.setGravity(Gravity.CENTER);
            tvDay.setLayoutParams(new LayoutParams(cellWidth, DAY_HEADER_HEIGHT));
            tvDay.setText(headers[i]);
            llHeaderContainer.addView(tvDay);
        }
	}

	/**
	 * 创建一个线形布局对象
	 * @param orientation 线形布局的方向
	 * @return 创建好的线形布局
	 */
	private LinearLayout createLayout(int orientation) {
		LinearLayout lay = new LinearLayout(getContext());
		lay.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
		lay.setOrientation(orientation);
		return lay;
	}
	
	/**
	 * 产生日历的一行
	 * @return
	 */
	private View generateCalendarRow() {
		LinearLayout llCalendarRow = createLayout(LinearLayout.HORIZONTAL);
		
		for (int i = 0; i < 7; i++) {
			DateCell dayCell = new DateCell(getContext(), cellWidth, cellHeight);
			
			dayCell.setItemClick(mOnDayCellClick);
			mDayCells.add(dayCell);
			
			llCalendarRow.addView(dayCell);
		}
		
		return llCalendarRow;
	}

	/**
	 * 修改单元格的状态
	 * @return
	 */
	private void updateCalendar() {
		
		boolean isSelection = (mSelectedDate.getTimeInMillis() != 0);
		
		int selectedYear = mSelectedDate.get(Calendar.YEAR);
		int selectedMonth = mSelectedDate.get(Calendar.MONTH);
		int selectedDay = mSelectedDate.get(Calendar.DAY_OF_MONTH);
		
		Calendar calendar =  Calendar.getInstance();
		calendar.setTimeInMillis(calStartDate.getTimeInMillis());
		
		//
		for (int i = 0; i < mDayCells.size(); i++) {
		
		    DateCell dayCell = mDayCells.get(i);
		    
			int year = calendar.get(Calendar.YEAR);
			int month = calendar.get(Calendar.MONTH);
			int day = calendar.get(Calendar.DAY_OF_MONTH);
			int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);

			boolean isToday = false;
			if (calToday.get(Calendar.YEAR) == year &&
				calToday.get(Calendar.MONTH) == month && 
				calToday.get(Calendar.DAY_OF_MONTH) == day) 
			{
				isToday = true;
			}
			

			boolean isHoliday = false;
			if ((dayOfWeek == Calendar.SATURDAY) || (dayOfWeek == Calendar.SUNDAY)) {
				isHoliday = true;
			}
			
			if ((month == Calendar.JANUARY) && (day == 1)) {
				isHoliday = true;
			}
			
			// 检查当前是否有收支情况
			boolean hasIncome = false;
			boolean hasOutlay = false;
			boolean hasOtherEvent = false;
			if (mIncomeAndExpensesStates != null) {
    			for (EventState iaes : mIncomeAndExpensesStates) {
    			    if (iaes.date.get(Calendar.YEAR) == year &&
    			            iaes.date.get(Calendar.MONTH) == month && 
    			            iaes.date.get(Calendar.DAY_OF_MONTH) == day) 
    			    {
    			        hasIncome = iaes.hasIncome;
    			        hasOutlay = iaes.hasExpenses;
    			        hasOtherEvent = iaes.hasOtherEvent;
    			        break;
    			    } 
    			}
			}

			dayCell.setDate(year, month, day, isToday, isHoliday, mMonthViewCurrentMonth, hasIncome, hasOutlay, hasOtherEvent);
			
			boolean isSelected = false;
			if (isSelection) {
				if ((selectedDay == day) && (selectedMonth == month)
						&& (selectedYear == year)) {
					isSelected = true;
				}
			}
			
			dayCell.setSelected(isSelected);
			
			calendar.add(Calendar.DAY_OF_MONTH, 1);
		}
		
		llCalendarDaysContainer.invalidate();
	}

	private void updateCurrentMonth() {
	  
	}
	
	private void updateStartDateForMonth() {
		mMonthViewCurrentMonth = calStartDate.get(Calendar.MONTH);
		mMonthViewCurrentYear = calStartDate.get(Calendar.YEAR);
		
		calStartDate.set(Calendar.DAY_OF_MONTH, 1);
		
//		updateCurrentMonth();
		
		mCurrentMonth.set(Calendar.YEAR, calStartDate.get(Calendar.YEAR));
        mCurrentMonth.set(Calendar.MONTH, calStartDate.get(Calendar.MONTH));
        mCurrentMonth.set(Calendar.DAY_OF_MONTH, calStartDate.get(Calendar.DAY_OF_MONTH));
        
//        String currentMonth = calStartDate.get(Calendar.YEAR) + " 年 " + ((calStartDate.get(Calendar.MONTH) + 1) +" 月");
        
        String currentMonth = Tools.format(calStartDate, "yyyy年MM月"); 
        
        btnToday.setText(currentMonth);
		
		
		int day = 0;
		int iStartDay = FISRT_DAY_OF_WEEK;
		if (iStartDay == Calendar.MONDAY) {
			day = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY;
			if (day < 0) {
				day = 6;
			}
		}
		
		if (iStartDay == Calendar.SUNDAY) {
			day = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
			if (day < 0) {
				day = 6;
			}
		}
		
		calStartDate.add(Calendar.DAY_OF_WEEK, -day);
	}

	/**
	 * 上一个月 
	 */
	private void setPrevViewItem() {
		mMonthViewCurrentMonth--;
		if (mMonthViewCurrentMonth == -1) {
			mMonthViewCurrentMonth = 11;
			mMonthViewCurrentYear--;
		}
		calStartDate.set(Calendar.DAY_OF_MONTH, 1);
		calStartDate.set(Calendar.MONTH, mMonthViewCurrentMonth);
		calStartDate.set(Calendar.YEAR, mMonthViewCurrentYear);
		
		updateStartDateForMonth();
		updateCalendar();
	}
	
	/**
	 * 显示下一个月 
	 */
	private void setNextViewItem() {
	
		mMonthViewCurrentMonth++;
		
		if (mMonthViewCurrentMonth == 12) {
			mMonthViewCurrentMonth = 0;
			mMonthViewCurrentYear++;
		}
		
		calStartDate.set(Calendar.DAY_OF_MONTH, 1);
		calStartDate.set(Calendar.MONTH, mMonthViewCurrentMonth);
		calStartDate.set(Calendar.YEAR, mMonthViewCurrentYear);
		
		updateStartDateForMonth();
		updateCalendar();

	}
	
    @Override
    public void onClick(View v)
    {
        int id = v.getId();
        switch (id) {
            case R.id.ibtn_pre_month:
                setPrevViewItem();
                if (onMonthChangeListener != null) {
                    onMonthChangeListener.onMonthChange(mCurrentMonth);
                }
                break;
            case R.id.tv_current_month:
                
                setTodayViewItem();
                
                mCurrentMonth.set(Calendar.YEAR, calToday.get(Calendar.YEAR));
                mCurrentMonth.set(Calendar.MONTH, calToday.get(Calendar.MONTH));
                if (onMonthChangeListener != null) {
                    onMonthChangeListener.onMonthChange(mCurrentMonth);
                }
//                String s = calToday.get(Calendar.YEAR) + " 年 " + (calToday.get(Calendar.MONTH) + 1) +" 月";
                
                String s = Tools.format(calToday, "yyyy年MM月");
                
                btnToday.setText(s);
                
                break;
            case R.id.ibtn_next_month:
                setNextViewItem();
                if (onMonthChangeListener != null) {
                    onMonthChangeListener.onMonthChange(mCurrentMonth);
                }
                
                break;
        }
    }

	/**
	 * 显示当前日期的月份
	 */
	public void setTodayViewItem() {
		calToday.setFirstDayOfWeek(FISRT_DAY_OF_WEEK);
		
		calStartDate.setTimeInMillis(calToday.getTimeInMillis());
		
		calStartDate.setFirstDayOfWeek(FISRT_DAY_OF_WEEK);
		
		updateStartDateForMonth();
		
		updateCalendar();
	}

    public Calendar getCurrentMonth() {
      return mCurrentMonth;
  }

	public void setEventStates(List<EventState> eventStates)
    {
        this.mIncomeAndExpensesStates = eventStates;
        updateCalendar();
    }

    public void setOnDateClickListener(OnDateClickListener onDateClickListener)
    {
        this.onDateClickListener = onDateClickListener;
    }

    public void setOnMonthChangeListener(OnMonthChangeListener onMonthChangeListener)
    {
        this.onMonthChangeListener = onMonthChangeListener;
    }

    /**
     * 用户点击日历上的日期的监听器
     */
    private DateCell.OnItemClick mOnDayCellClick = new DateCell.OnItemClick() {
		public void OnClick(DateCell item) {
			mSelectedDate.setTimeInMillis(item.getDate().getTimeInMillis());
			
			item.setSelected(true);
			
			updateCalendar();
			
			if (onDateClickListener != null) {
			    onDateClickListener.onDateClick(item.getDate());
			}
		}
	};
	
	/**
	 * 清除选中状态
	 */
	public void clearSelected() {
	    mSelectedDate.clear();
	    for (DateCell dc : mDayCells) {
	        dc.setSelected(false);
	    }
	    invalidate();
	}
	
	/**
	 * 日期下的事件状态
	 * 总共包含3种状态
	 * 1.有收入
	 * 2.有支出
	 * 3.其它事件
	 * 
	 * 3种状态可以同时存在
	 * @author EX-XIAOFANQING001
	 * @version [Android PABank C01, 2011-12-29]
	 */
	public static class EventState {
	    
	    private Calendar date;
	    private boolean hasIncome;
	    private boolean hasExpenses;
	    private boolean hasOtherEvent;
	    
	    public EventState() {
	        
	    }
	    
	    public EventState (Calendar date, boolean hasIncome, boolean hasExpenses) {
	        this.setDate(date);
	        
	        this.hasIncome = hasIncome;
	        this.hasExpenses = hasExpenses;
	    }
	    
	    public EventState (Calendar date, boolean hasIncome, boolean hasExpenses, boolean hasOtherEvent) {
	        this(date, hasIncome, hasExpenses);
	        this.setHasOtherEvent(hasOtherEvent);
	    }

        public boolean isHasIncome()
        {
            return hasIncome;
        }

        public void setHasIncome(boolean hasIncome)
        {
            this.hasIncome = hasIncome;
        }

        public boolean isHasExpenses()
        {
            return hasExpenses;
        }

        public void setHasExpenses(boolean hasExpenses)
        {
            this.hasExpenses = hasExpenses;
        }


        public void setDate(Calendar date)
        {
            this.date = date;
        }


        public Calendar getDate()
        {
            return date;
        }

        public void setHasOtherEvent(boolean hasOtherEvent)
        {
            this.hasOtherEvent = hasOtherEvent;
        }

        public boolean isHasOtherEvent()
        {
            return hasOtherEvent;
        }

        @Override
        public String toString()
        {
            return "EventState [date=" + date + ", hasIncome=" + hasIncome + ", hasExpenses=" + hasExpenses
                    + ", hasOtherEvent=" + hasOtherEvent + "]";
        }
	}
	
	/**
	 * 日历点击监听器
	 * @author EX-XIAOFANQING001
	 * @version [Android PABank C01, 2011-12-29]
	 */
	public interface OnDateClickListener{
	    /**
	     * 点击日期的监听事件
	     * @param date 点击的日期对象
	     */
	    public void onDateClick(Calendar date);
	}
	
	/**
	 * 月份切换监听器<BR>
	 *  
	 * @author EX-XIAOFANQING001
	 * @version [Android PABank C01, 2011-12-29]
	 */
	public interface OnMonthChangeListener {
	    /**
	     * 当用户点击切换月份的按钮时
	     * @param month 切换到的月份
	     */
	    public void onMonthChange(Calendar month);
	}
}
